#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <netinet/in.h>

#define N 128

#define ERR_LOG(errmsg) do{\
                            perror(errmsg);\
	                    exit(1);\
                          }while(0)

int main(int argc,char const *argv[])
{
    //输入参数：ip和端口。
    if(argc<3){
       fprintf(stderr,"Usage: %s [ip] [port]\n",argv[0]);
       exit(1);
    }

    int sockfd;
    if((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1){
         ERR_LOG("fail to socket");
    }

    // printf("sockfd = %d\n",sockfd);
    // 第二步：发送连接请求
    struct sockaddr_in serveraddr;
    socklen_t addrlen = sizeof(serveraddr);
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    serveraddr.sin_port = htons(atoi(argv[2]));//port必须是一个整形，atoi自动将字符转化成整形

    if(connect(sockfd,(struct sockaddr *)&serveraddr,addrlen)== -1){//sockaddr进行强转，是因为上面定义的结构体类型是sockaddr_in。
         ERR_LOG("fail to connect");
    }
    printf("connected!\n");

    //第三步:通信
    char buf[N]="";
    while(1){
	//fgets默认也是阻塞的
       fgets(buf,N,stdin);//读取终端中用户的输入到缓冲区buf中。成功时返回指向缓冲区(buf)的指针。
       buf[strlen(buf)-1]='\0';//数组最后一个元素设置为结束符

       if(send(sockfd,buf,N,0)<0){
          ERR_LOG("fail to send");
       }

       if(strncmp(buf,"quit",4)==0){//strncmp比较两字符串的前n个字符，如果一致返回
          exit(0);//这里表示如果用户输入的是quit则退出循环
       }

       //这里的recv默认是阻塞的，也就是说循环到这里会等待服务器消息才能继续执行
       if(recv(sockfd,buf,N,0)<0){//接收服务器消息
          ERR_LOG("fail to recv");
       }

       printf("from server: %s\n",buf);
    }    

    //关闭
    close(sockfd);
    return 0;
}
